﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Data;
using System.Text;
using System.Web;
using System.Transactions;
using FreedomERP.Services.Bd.Impl;
using FreedomERP.Comm;
using FreedomERP.Comm.Utils;
using FreedomERP.Comm.DB;
using FreedomERP.Models;
using FreedomERP.Models.Bd;

namespace FreedomERP.Dao.Bd.Impl
{
    public class BdProductDaoImpl : IBdProductDao
    {
        FreedomERPEntities dbEntities = new FreedomERPEntities();

        public DAOResult<BdProduct> getProducts(String fId, String fOrgunited, String fNumber, String fName, String fModelId, String fUnitId, String fReMark, String fStatusId, String fFromQty, String fEndQty, String fProdInvStatusName, String sortColumn, Boolean isASC, int start, int limit, out int totalCount)
        {
            Expression<Func<BdProduct, bool>> predicate = PredicateExtensions.True<BdProduct>();
            if (fId != null && ConstData.EMPTY_STRING != fId)
            {
                predicate = predicate.And(prod => prod.FId.Contains(fId));
            }
            if (fOrgunited != null && ConstData.EMPTY_STRING != fOrgunited)
            {
                predicate = predicate.And(prod => prod.FOrgunitId.Contains(fOrgunited));
            }
            if (fNumber != null && ConstData.EMPTY_STRING != fNumber)
            {
                predicate = predicate.And(prod => prod.FNumber.Equals(fNumber));
            }
            if (fName != null && ConstData.EMPTY_STRING != fName)
            {
                predicate = predicate.And(prod => prod.FName.Contains(fName));
            }
            if (fModelId != null && ConstData.EMPTY_STRING != fModelId)
            {
                predicate = predicate.And(prod => prod.FModelId.Contains(fModelId));
            }
            if (fUnitId != null && ConstData.EMPTY_STRING != fUnitId)
            {
                predicate = predicate.And(prod => prod.FUnitId.Contains(fUnitId));
            }
            if (fReMark != null && ConstData.EMPTY_STRING != fReMark)
            {
                predicate = predicate.And(prod => prod.FRemark.Contains(fReMark));
            }
            if (fStatusId != null && ConstData.EMPTY_STRING != fStatusId)
            {
                predicate = predicate.And(prod => prod.FStatusId.Contains(fStatusId));
            }
            if (fFromQty != null && ConstData.EMPTY_STRING != fFromQty)
            {
                long fromQty = Int64.Parse(fFromQty);
                predicate = predicate.And(prod => prod.FQty.Value >= fromQty);
            }
            if (fEndQty != null && ConstData.EMPTY_STRING != fEndQty)
            {
                long endQty = Int64.Parse(fEndQty);
                predicate = predicate.And(prod => prod.FQty.Value <= endQty);
            }
            if (fProdInvStatusName != null && ConstData.EMPTY_STRING != fEndQty)
            {
                if (fProdInvStatusName == ConstData.CATEGORY_PROD_INV_STATUS_NORMAL)
                {
                    long qty = Int64.Parse("0");
                    predicate = predicate.And(prod => prod.FQty.Value >= qty);
                }
                else if (fProdInvStatusName == ConstData.CATEGORY_PROD_INV_STATUS_SHORTAGE)
                {
                    long qty = Int64.Parse("0");
                    predicate = predicate.And(prod => prod.FQty.Value < qty);
                }
            }
            var query = dbEntities.BdProduct.Where(predicate);
            totalCount = query.Count();
            List<BdProduct> products = null;
            if (sortColumn == null && sortColumn == string.Empty)
            {
                products = query.OrderByDescending(prod => prod.FModifyTime).Skip(start).Take(limit).ToList();
            }
            else
            {
                if (sortColumn == "ProductNumber")
                {
                    if (isASC)
                    {
                        products = query.OrderBy(prod => prod.FNumber).Skip(start).Take(limit).ToList();
                    }
                    else
                    {
                        products = query.OrderByDescending(prod => prod.FNumber).Skip(start).Take(limit).ToList();
                    }

                }
                else
                {
                    products = query.OrderByDescending(prod => prod.FModifyTime).Skip(start).Take(limit).ToList();
                }
            }


            return new DAOResult<BdProduct>(true, null, products);
        }

        public DAOResult<ProductInfo> getProductInfos(String fId, String fOrgunited, String fNumber, String fName, String fModelId, String fUnitId, String fReMark, String fStatusId, String fFromQty, String fEndQty, String fProdInvStatusName, String sortColumn, Boolean isASC, int start, int limit, out int totalCount)
        {

            DAOResult<BdProduct> products = getProducts(fId, fOrgunited, fNumber, fName, fModelId, fUnitId, fReMark, fStatusId, fFromQty, fEndQty, fProdInvStatusName, sortColumn, isASC, start, limit, out totalCount);
            if (products.result == false)
            {
                return new DAOResult<ProductInfo>(false, products.msg, null);
            }
            else
            {
                List<ProductInfo> productInfos = new List<ProductInfo>();
                foreach (var bdProduct in products.resultSet)
                {
                    ProductInfo productInfo = new ProductInfo();
                    productInfo.ProductId = bdProduct.FId;
                    productInfo.ProductNumber = bdProduct.FNumber;
                    productInfo.ProductName = bdProduct.FName;
                    if (bdProduct.BdCategory2 != null)
                    {
                        productInfo.ProductUnitName = bdProduct.BdCategory2.FName;
                        productInfo.ProductUnitId = bdProduct.BdCategory2.FId;
                    }
                    productInfo.ProductQty = bdProduct.FQty;
                    productInfo.ProductRemark = bdProduct.FRemark;
                    if (bdProduct.BdCategory1 != null)
                    {
                        productInfo.ProductStatus = bdProduct.BdCategory1.FName;
                        productInfo.ProductStatusId = bdProduct.BdCategory1.FId;
                    }
                    if (bdProduct.BdCategory != null)
                    {
                        productInfo.ProductModelName = bdProduct.BdCategory.FName;
                        productInfo.ProductModelId = bdProduct.BdCategory.FId;
                    }
                    if (bdProduct.BdCategory2 != null)
                    {
                        productInfo.ProductUnitName = bdProduct.BdCategory2.FName;
                        productInfo.ProductUnitId = bdProduct.BdCategory2.FId;
                    }
                    productInfo.ProductOrgId = bdProduct.FOrgunitId;
                    productInfo.ProductOrgName = bdProduct.BdOrgunit.FName;
                    if (bdProduct.FModifyTime != null)
                    {
                        productInfo.LastModeifyTime = bdProduct.FModifyTime;

                    }
                    else
                    {
                        productInfo.LastModeifyTime = bdProduct.FCreateTime;
                    }
                    Hashtable pricesMap = new Hashtable();
                    foreach (var bdProdPrice in bdProduct.BdProductPrice.ToList())
                    {
                        BdCategory priceType = bdProdPrice.BdCategory;
                        pricesMap.Add(priceType.FName, bdProdPrice.FPrice);
                    }
                    productInfo.prices = pricesMap;
                    productInfos.Add(productInfo);
                }
                return new DAOResult<ProductInfo>(true, null, productInfos);
            }
        }



        public DAOResult<String> saveOrUpdateProductInfo(ProductInfo productinfo, String fAccountId)
        {
            String returnFID = null;
            BdProduct bdProduct = new BdProduct();
            if (fAccountId == null || productinfo == null)
            {
                return new DAOResult<String>(false, "产品参数为空或用户名参数为空,无法保存。", null);
            }
            String Fid = productinfo.ProductId;
            if (Fid == null)//新增产品
            {

                bdProduct.FId = GuidUtils.getGuid();
                returnFID = bdProduct.FId;
                IBdOrgunitDao orgDao = new BdOrgunitDaoImpl();
                BdOrgunit bdOrgunit = orgDao.findOrgunitById(productinfo.ProductOrgId);
                if (bdOrgunit == null)
                {
                    return new DAOResult<String>(false, "数据库找不到相关的商户信息，无法保存。", null);
                }
                List<BdProduct> ifProducts = (from ifProd in dbEntities.BdProduct where ifProd.FId == productinfo.ProductId select ifProd).ToList<BdProduct>();
                if (ifProducts.Count > 0)
                {
                    return new DAOResult<String>(false, "该商品已存在，无法保存。", null);
                }
                List<BdProduct> ifProductNumbers = (from ifProd in dbEntities.BdProduct where ifProd.FNumber == productinfo.ProductNumber && ifProd.FStatusId == productinfo.ProductStatusId select ifProd).ToList<BdProduct>();
                if (ifProductNumbers.Count > 0)
                {
                    return new DAOResult<String>(false, "该商品编号已存在，无法保存。", null);
                }
                bdProduct.FOrgunitId = productinfo.ProductOrgId;
                bdProduct.FName = productinfo.ProductName;
                bdProduct.FNumber = productinfo.ProductNumber;
                bdProduct.FUnitId = productinfo.ProductUnitId;
                bdProduct.FCreatorId = fAccountId;
                bdProduct.FCreateTime = DateTime.Now;
                bdProduct.FModifierId = fAccountId;
                bdProduct.FModifyTime = bdProduct.FCreateTime;
                bdProduct.FModelId = productinfo.ProductModelId;
                bdProduct.FQty = productinfo.ProductQty;
                bdProduct.FRemark = productinfo.ProductRemark;
                bdProduct.FStatusId = productinfo.ProductStatusId;
                IBdCategoryDao categoryDao = new BdCategoryDaoImpl();
                if (productinfo.prices == null)
                {
                    return new DAOResult<String>(false, "价格信息不存在，无法保存。", null);
                }
                foreach (DictionaryEntry entry in productinfo.prices)
                {
                    if (ConstData.EMPTY_STRING.Equals(entry.Value))
                        continue;
                    BdProductPrice prodPrice = new BdProductPrice();
                    prodPrice.FId = GuidUtils.getGuid();
                    prodPrice.FCreateTime = DateTime.Now;
                    prodPrice.FCreatorId = fAccountId;
                    prodPrice.FPrice = Convert.ToDecimal(entry.Value);
                    int totalCount = 0;
                    List<BdCategory> priceCates = categoryDao.findProdPriceTypes(null, productinfo.ProductOrgId, (String)entry.Key, null, null, false, 0, 1, out totalCount).resultSet;
                    BdCategory priceCate = null;
                    if (priceCates == null || priceCates.Count <= 0)
                    {
                        return new DAOResult<String>(false, "保存失败，价格类型不存在", null);

                    }
                    else
                    {
                        priceCate = priceCates.First();
                        prodPrice.FType = priceCate.FId;
                    }
                    bdProduct.BdProductPrice.Add(prodPrice);
                }
                dbEntities.BdProduct.AddObject(bdProduct);
            }
            else //更新产品
            {
                List<BdProduct> products = (from prod in dbEntities.BdProduct where prod.FId.Equals(productinfo.ProductId) select prod).ToList<BdProduct>();
                if (products.Count == 0)
                {

                    return new DAOResult<String>(false, "该产品ID无效，更新失败", null);
                }
                else
                {
                    BdProduct dbProd = products.First<BdProduct>();
                    List<BdOrgunit> bdOrgunits = (from bdOrg in dbEntities.BdOrgunit where bdOrg.FId == productinfo.ProductOrgId select bdOrg).ToList<BdOrgunit>();
                    if (bdOrgunits.Count <= 0)
                    {
                        return new DAOResult<String>(false, "数据库找不到相关的商户信息，无法更新。", null);
                    }
                    List<BdProduct> ifProducts = (from ifProd in dbEntities.BdProduct where ifProd.FId == productinfo.ProductId select ifProd).ToList<BdProduct>();
                    if (ifProducts.Count <= 0)
                    {
                        return new DAOResult<String>(false, "该商品不存在，无法更新。", null);
                    }
                    if (dbProd.FNumber != productinfo.ProductNumber)
                    {
                        return new DAOResult<String>(false, "商品编号不能修改，更新失败。", null);
                    }
                    dbProd.FOrgunitId = productinfo.ProductOrgId;
                    dbProd.FName = productinfo.ProductName;
                    dbProd.FNumber = productinfo.ProductNumber;
                    dbProd.FUnitId = productinfo.ProductUnitId;
                    dbProd.FModifierId = fAccountId;
                    dbProd.FModifyTime = DateTime.Now;
                    dbProd.FModelId = productinfo.ProductModelId;
                    dbProd.FQty = productinfo.ProductQty;
                    dbProd.FRemark = productinfo.ProductRemark;
                    dbProd.FStatusId = productinfo.ProductStatusId;
                    IBdCategoryDao categoryDao = new BdCategoryDaoImpl();
                    if (productinfo.prices == null)
                    {
                        return new DAOResult<String>(false, "价格信息不存在，无法更新。", null);
                    }
                    int dbProductPriceCount = dbProd.BdProductPrice.Count;
                    for (int j = 0; j < dbProductPriceCount; j++)
                    {

                        BdProductPrice dbProdPrice = dbProd.BdProductPrice.ElementAt(0);
                        dbEntities.BdProductPrice.DeleteObject(dbProdPrice);

                    }
                    dbProd.BdProductPrice.Clear();
                    foreach (DictionaryEntry entry in productinfo.prices)
                    {
                        if (ConstData.EMPTY_STRING.Equals(entry.Value))
                            continue;
                        BdProductPrice prodPrice = new BdProductPrice();
                        prodPrice.FId = GuidUtils.getGuid();
                        prodPrice.FCreateTime = DateTime.Now;
                        prodPrice.FCreatorId = fAccountId;
                        prodPrice.FPrice = Convert.ToDecimal(entry.Value);
                        int totalCount = 0;
                        List<BdCategory> priceCates = categoryDao.findProdPriceTypes(null, productinfo.ProductOrgId, (String)entry.Key, null, null, false, 0, 1, out totalCount).resultSet;
                        BdCategory priceCate = null;

                        if (priceCates == null || priceCates.Count <= 0)
                        {
                            return new DAOResult<String>(false, "更新失败，价格类型不存在", null);
                        }
                        else
                        {
                            priceCate = priceCates.First();
                            prodPrice.FType = priceCate.FId;
                        }

                        dbProd.BdProductPrice.Add(prodPrice);
                    }
                    returnFID = dbProd.FId;
                }
            }
            dbEntities.SaveChanges();
            List<String> resultSet = new List<String>();
            resultSet.Add(returnFID);
            return new DAOResult<String>(true, null, resultSet);
        }


        public DAOResult<BdProduct> deleteProduct(String productId)
        {

            List<BdProduct> products = (from prod in dbEntities.BdProduct where prod.FId == productId select prod).ToList<BdProduct>();
            if (products.Count <= 0)
                return new DAOResult<BdProduct>(false, "商品信息不存在，无法删除。", null);
            else
            {
                BdProduct product = products.First<BdProduct>();
                List<InvSendOrderDetail> sendOrderDetails = (from sendOrdDetail in dbEntities.InvSendOrderDetail where (sendOrdDetail.BdProduct.FId == product.FId && sendOrdDetail.InvSendOrder.BdCategory.FType == ConstData.CATEGORY_SEND_ORDER_STATUS && (sendOrdDetail.InvSendOrder.BdCategory.FNumber == ConstData.CATEGORY_SEND_ORDER_STATUS_SAVE || sendOrdDetail.InvSendOrder.BdCategory.FNumber == ConstData.CATEGORY_SEND_ORDER_STATUS_APPROVE)) select sendOrdDetail).ToList();
                if (sendOrderDetails.Count > 0)
                {
                    return new DAOResult<BdProduct>(false, "该产品信息在送货单中被引用，无法删除", null);
                }

                IBdCategoryDao cateDao = new BdCategoryDaoImpl();
                int totalCount = 0;
                String unValidStatusId = cateDao.findProdStatusTypes(null, product.FOrgunitId, ConstData.PRODUCT_STATUS_NO, null, null, false, 0, 1, out totalCount).resultSet.First<BdCategory>().FId;
                product.FStatusId = unValidStatusId;
                dbEntities.SaveChanges();
                return new DAOResult<BdProduct>(true, null, null);
            }

        }


        /// <summary>
        /// 根据产品FNumber获取产品信息
        /// </summary>
        /// <param name="FNumber"></param>
        /// <author>梁建东</author>
        /// <returns></returns>
        public ProductInfo GetProductMsgByFNumber(String FNumber)
        {
            ProductInfo productInf = (from prod in dbEntities.BdProduct where prod.FNumber == FNumber select new ProductInfo { ProductId = prod.FId, ProductName = prod.FName, ProductNumber = prod.FNumber }).First<ProductInfo>();
            return productInf;
        }

        /// <summary>
        /// 根据FId获取产品
        /// </summary>
        /// <param name="FId"></param>
        /// <author>姚少鹏</author>
        /// <returns></returns>
        public BdProduct getProductByFId(String FId)
        {
            BdProduct obj = null;

            List<BdProduct> productList = (from ba in dbEntities.BdProduct where ba.FId == FId select ba).ToList<BdProduct>();
            if (productList != null && productList.Count > 0)
                obj = productList.First();

            return obj;
        }

        /// <summary>
        /// 根据产品类型获取产品信息
        /// </summary>
        /// <param name="FType"></param>
        /// <author>姚少鹏</author>
        /// <returns></returns>
        public List<ProductInfo> getProductInfoByFType(String FType)
        {
            List<BdProductPrice> productPriceList = (from ba in dbEntities.BdProductPrice where ba.FType == FType select ba).ToList<BdProductPrice>();
            List<BdProduct> productList = dbEntities.BdProduct.ToList<BdProduct>();
            List<BdCategory> categoryList = dbEntities.BdCategory.ToList<BdCategory>();
            List<ProductInfo> productInfoList = new List<ProductInfo>();
            ProductInfo productInfo = null;
            foreach (BdProduct product in productList)
            {
                productInfo = new ProductInfo();
                productInfo.ProductId = product.FId;
                productInfo.ProductName = product.FName;
                productInfo.ProductNumber = product.FNumber;
                productInfo.ProductUnitId = product.FUnitId;
                productInfo.ProductModelId = product.FModelId;
                productInfo.ProductQty = product.FQty;
                productInfo.ProductRemark = product.FRemark;
                productInfo.ProductStatusId = product.FStatusId;
                productInfo.ProductOrgId = product.FOrgunitId;
                foreach (BdProductPrice productPrice in productPriceList)
                {
                    if (productInfo.ProductId == productPrice.FProductId)
                        productInfo.ProductPrice = productPrice.FPrice;
                }
                foreach (BdCategory category in categoryList)
                {
                    if (productInfo.ProductModelId == category.FId)
                        productInfo.ProductModelName = category.FName;
                }
                productInfoList.Add(productInfo);
            }
            return productInfoList;
        }
    }
}
